/*
----------------------------------------------------------------------------------------------------
This source file is part of the Gamut Framework
Copyright (c) 2007 by Ryan Holcombe

This program is free software; you can redistribute it and/or modify it under the terms of the GNU
Lesser General Public License as published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
----------------------------------------------------------------------------------------------------
*/

#include "GamutGameObjectManager.h"
#include "GamutIGameObject.h"
#include "GamutException.h"
#include "GamutLogger.h"

namespace Gamut
{
	// -------------------------------------------------------------------------------------------//
	GameObjectManager::GameObjectManager(const std::string& name, unsigned int priority) :
		IManager(name, priority)
	{
		mGOMap.clear();
	}
	
	// -------------------------------------------------------------------------------------------//
	GameObjectManager::~GameObjectManager()
	{			
		// destroy all left over game objects
		while (mGOMap.size() > 0)
		{
			destroyGameObject(mGOMap.begin()->first);
		}
	}
	
	// -------------------------------------------------------------------------------------------//
	void GameObjectManager::tick(double elapsed)
	{
		// process each game object
		for (GameObjectMap::iterator iter = mGOMap.begin(); iter != mGOMap.end(); iter++)
			iter->second->tick(elapsed);
	}
	
	// -------------------------------------------------------------------------------------------//
	void GameObjectManager::addGameObject(std::string name, IGameObject *go)
	{
		// make sure the game object name does not already exist in the map
		if (mGOMap.find(name) != mGOMap.end())
			throw Exception("GameObjectManager::addGameObject", "Game Object [" + name +
							"] already exists in the map");
		
		// make sure the pointer does not already exists
		for (GameObjectMap::iterator iter = mGOMap.begin(); iter != mGOMap.end(); iter++)
		{
			if (go == iter->second)
				throw Exception("GameObjectManager::addGameObject", "Game Object pointer to [" + name +
								"] already exists in the map as [" + iter->first + "]");
		}

		mGOMap.insert(name, go);

		// set name
		go->mName = name;

		go->onAdd();
				
		LOG3("Game Object [" + name + "] added");
	}
	
	// -------------------------------------------------------------------------------------------//
	void GameObjectManager::destroyGameObject(std::string name)
	{
		GameObjectMap::iterator iter = mGOMap.find(name);
		
		// make sure the name exists in the map
		if (iter == mGOMap.end())
		{
			LOG2("Unable to find game object [" + name + "] in map");
			return;
		}
		
		iter->second->onDestroy();
		mGOMap.erase(iter);
		LOG3("Game Object [" + name + "] destroyed");
	}
	
	// -------------------------------------------------------------------------------------------//
	void GameObjectManager::destroyGameObject(IGameObject *go)
	{
		GameObjectMap::iterator iter = mGOMap.begin();
		
		while (iter->second != go)
		{
			if (iter == mGOMap.end())
			{
				LOGF2("Unable to find game object (%p) in map", go);
				return;
			}
		}
		
		destroyGameObject(iter->first);
	}
	
	// -------------------------------------------------------------------------------------------//
	IGameObject *GameObjectManager::getGameObject(std::string name)
	{
		GameObjectMap::iterator iter = mGOMap.find(name);
		
		if (iter == mGOMap.end())
		{
			LOG2("Unable to find game object [" + name + "] in map");
			return (NULL);
		}
		
		return (iter->second);
	}
}
